package com.example.usercenter.config.security.jwt;

import com.alibaba.fastjson.JSONObject;
import com.example.usercenter.sys.entity.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;

/**
 * Created by zxn on 2018/7/30.
 */
public class TokenAuthenticationService {
    static final long EXPIRATIONTIME = 432_000_000;     // 5天
    static final String SECRET = "P@ssw02d";            // JWT密码
    static final String TOKEN_PREFIX = "Bearer";        // Token前缀
    static final String HEADER_TOKEN = "X-Token";// 存放Token的Header Key
    static final String PARAM_TOKEN = "token";// 存放Token的Header Key
    static final String USER_DETAIL = "UserDetail";// 存放UserDetail的Header Key

    // JWT生成方法
    public static String addAuthentication(User userDetail) throws IOException {
        JSONObject json = (JSONObject) JSONObject.toJSON(userDetail);
        //移除多余用户属性，减少token长度
        json.remove("password");
        json.remove("avatar");
        json.remove("enabled");
        json.remove("accountNonExpired");
        json.remove("accountNonLocked");
        json.remove("credentialsNonExpired");
        json.remove("authorities");
        json.remove("fullAddress");
        json.remove("roles");
        // 生成JWT
        return Jwts.builder()
                // 保存用户详情
                .claim(USER_DETAIL, json.toString())
                // 用户名写入标题
                .setSubject(userDetail.getUsername())
                // 有效期设置
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME))
                // 签名设置
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .compact();
    }

    // JWT验证方法
    public static Authentication getAuthentication(HttpServletRequest request) {
        // 从Header中拿到token
        String token = request.getHeader(HEADER_TOKEN);
        if (token != null) {
            // 解析 Token
            Claims claims = Jwts.parser()
                    // 验签
                    .setSigningKey(SECRET)
                    // 去掉 Bearer
                    .parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
                    .getBody();
            // 拿用户名
            String username = claims.getSubject();
            // 权限
            Collection<? extends GrantedAuthority> authorities =  null;
            // 用户详情
            User userDetail = null;
            try {
                userDetail = new ObjectMapper().readValue((String)claims.get(USER_DETAIL), User.class);
                authorities =  userDetail.getAuthorities();
            } catch (IOException e) {
                e.printStackTrace();
                userDetail = new User();
                userDetail.setUsername(username);
            }
            // 返回验证令牌
            return username != null ?
                    new UsernamePasswordAuthenticationToken(userDetail, null, authorities) :
                    null;
        }
        return null;
    }
}
